package network.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import common.util.MapUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import common.model.Entity.User;
import common.util.JsonUtil;
import lombok.Getter;
import network.protocol.Request;
import network.protocol.Response;
import network.server.session.SessionManager;

/**
 * ClientHandler 负责处理单个客户端的通信，包括：
 * - 读取客户端请求
 * - 解析 JSON 请求
 * - 调用 RequestDispatcher 分发处理
 * - 发送响应给客户端
 * - 管理登录状态与会话
 */
public class ClientHandler implements Runnable {

    private static final Logger logger = LoggerFactory.getLogger(ClientHandler.class);
    private final Socket socket;
    private final RequestDispatcher dispatcher;
    private String guestSessionId;

    /**
     * 当前已登录用户信息
     */
    @Getter
    private User currentUser;

    private volatile boolean running = true; // 线程运行标志

    private BufferedReader in;
    private PrintWriter out;

    /**
     * 构造函数
     *
     * @param socket     客户端 Socket
     * @param dispatcher 请求分发器
     */
    public ClientHandler(Socket socket, RequestDispatcher dispatcher) {
        this.socket = socket;
        this.dispatcher = dispatcher;
        this.guestSessionId = "guest_" + UUID.randomUUID().toString().substring(0, 8);
    }

    /**
     * 客户端处理线程入口
     */
    @Override
    public void run() {
        try {
            initConnection();

            char[] buffer = new char[8192]; // 8KB缓冲区
            StringBuilder requestBuilder = new StringBuilder();
            int consecutiveEmptyReads = 0;
            final int MAX_CONSECUTIVE_EMPTY_READS = 10;

            while (running) {
                int bytesRead = in.read(buffer);

                if (bytesRead == -1) {
                    logger.info("客户端连接已关闭");
                    break;
                }

                if (bytesRead == 0) {
                    consecutiveEmptyReads++;
                    if (consecutiveEmptyReads > MAX_CONSECUTIVE_EMPTY_READS) {
                        logger.warn("连续多次读取到空数据，可能连接有问题");
                        break;
                    }
                    Thread.sleep(100);
                    continue;
                }

                consecutiveEmptyReads = 0;
                requestBuilder.append(buffer, 0, bytesRead);
                String receivedData = requestBuilder.toString();

                int processed = processCompleteJsonRequests(receivedData, requestBuilder);

                if (processed == 0) {
                    if (requestBuilder.length() > 65536) {
                        logger.error("缓冲区过大，可能包含无效数据，清空缓冲区");
                        requestBuilder.setLength(0);
                    }
                }
            }
        } catch (IOException e) {
            if (running) {
                logger.error("连接异常: {}", e.getMessage());
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.info("客户端处理线程被中断");
        } finally {
            closeConnection();
        }
    }

    /**
     * JSON提取结果
     */
    private static class JsonExtractionResult {
        final String jsonObject;
        final int endIndex;

        JsonExtractionResult(String jsonObject, int endIndex) {
            this.jsonObject = jsonObject;
            this.endIndex = endIndex;
        }
    }

    /**
     * 处理所有完整的 JSON 请求
     *
     * @param receivedData   当前接收的数据
     * @param requestBuilder StringBuilder 缓冲区
     * @return 已处理的请求数量
     */
    private int processCompleteJsonRequests(String receivedData, StringBuilder requestBuilder) {
        int processedCount = 0;
        String remainingData = receivedData;

        while (true) {
            JsonExtractionResult extractionResult = extractNextJsonObject(remainingData);

            if (extractionResult.jsonObject != null) {
                processSingleRequest(extractionResult.jsonObject);
                processedCount++;
                remainingData = remainingData.substring(extractionResult.endIndex);

                if (remainingData.length() < 100) {
                    break;
                }
            } else {
                break;
            }
        }

        requestBuilder.setLength(0);
        requestBuilder.append(remainingData);

        return processedCount;
    }

    /**
     * 从字符串中提取下一个完整的 JSON 对象
     *
     * @param data 输入字符串
     * @return JsonExtractionResult 包含 JSON 字符串及结束索引
     */
    private JsonExtractionResult extractNextJsonObject(String data) {
        if (data == null || data.trim().isEmpty()) {
            return new JsonExtractionResult(null, 0);
        }

        int startIndex = -1;
        for (int i = 0; i < data.length(); i++) {
            if (data.charAt(i) == '{') {
                startIndex = i;
                break;
            }
        }

        if (startIndex == -1) {
            return new JsonExtractionResult(null, 0);
        }

        int braceCount = 0;
        boolean inString = false;
        boolean escaped = false;
        int endIndex = -1;

        for (int i = startIndex; i < data.length(); i++) {
            char c = data.charAt(i);

            if (escaped) {
                escaped = false;
                continue;
            }

            if (c == '\\') {
                escaped = true;
                continue;
            }

            if (c == '"') {
                inString = !inString;
                continue;
            }

            if (!inString) {
                if (c == '{') {
                    braceCount++;
                } else if (c == '}') {
                    braceCount--;
                    if (braceCount == 0) {
                        endIndex = i + 1;
                        break;
                    }
                }
            }
        }

        if (endIndex != -1) {
            String jsonObject = data.substring(startIndex, endIndex).trim();
            return new JsonExtractionResult(jsonObject, endIndex);
        }

        return new JsonExtractionResult(null, 0);
    }

    /**
     * 处理单个 JSON 请求
     *
     * @param jsonRequest JSON 字符串
     */
    private void processSingleRequest(String jsonRequest) {
        try {
            logger.info("接收到请求: {}", jsonRequest);

            if (!jsonRequest.trim().startsWith("{") || !jsonRequest.trim().endsWith("}")) {
                logger.warn("无效的JSON格式: {}", jsonRequest);
                return;
            }

            Request request = JsonUtil.fromJson(jsonRequest, Request.class);

            if (request != null && request.getAction() != null) {
                Response<?> response = dispatcher.handle(request);
                send(response);
            } else {
                logger.warn("无效的请求格式: {}", jsonRequest);
                send(Response.error("无效的请求格式"));
            }

        } catch (Exception e) {
            logger.error("解析请求时出错: {} - {}", e.getMessage(), jsonRequest, e);
            send(Response.error("请求解析错误: " + e.getMessage()));
        }
    }

    /**
     * 初始化输入输出流，并创建游客会话
     */
    private void initConnection() throws IOException {
        in = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
        out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8), true);
        socket.setTcpNoDelay(true);
        socket.setKeepAlive(true);

        String userSessionId = SessionManager.addSession(true,this.guestSessionId,this);
        if(send(Response.success(userSessionId))){
            logger.info("回传sessionId成功");
        }else{
            logger.error("回传sessionId失败");
        }

        System.out.println("客户端已连接: " + socket.getRemoteSocketAddress());
    }

    /**
     * 检查连接是否有效
     *
     * @return true 如果连接有效
     */
    public boolean isConnected() {
        return socket != null &&
                !socket.isClosed() &&
                socket.isConnected() &&
                out != null &&
                !out.checkError() &&
                running;
    }

    /**
     * 向客户端发送响应
     *
     * @param response Response 对象
     * @return 是否发送成功
     */
    public boolean send(Response<?> response) {
        if (response == null) {
            logger.warn("尝试发送空的响应");
            return false;
        }

        if (!isConnected()) {
            logger.warn("连接已断开，无法发送响应");
            return false;
        }

        Map<String,Object> responseMap = new HashMap<>();
        responseMap.put("Response" , response);

        if (response.getData() instanceof Map<?, ?> dataMap) {
            if (dataMap.containsKey("requestId")) {
                responseMap.put("requestId", dataMap.get("requestId"));
            }
        }

        try {
            String json = JsonUtil.toJson(responseMap);

            if (json.startsWith("\uFEFF")) {
                json = json.substring(1);
            }
            json = json.replaceAll("[\\r\\n]", "") + "\n";

            synchronized (out) {
                out.println(json);
                out.flush();
            }

            logger.debug("响应发送成功 - 状态码: {}", response.getCode());
            return true;

        } catch (Exception e) {
            logger.error("发送响应失败: {}", e.getMessage());
            closeConnection();
            return false;
        }
    }

    /**
     * 登录成功后绑定当前用户
     *
     * @param user 登录的 User 对象
     * @return 新的 SessionId
     */
    public String bindUser(User user) {
        this.currentUser = user;
        SessionManager.removeSession(true,this.guestSessionId);
        this.currentUser=user;
        this.guestSessionId=null;
        return SessionManager.addSession(false, user.getId().toString(), this);
    }

    /**
     * 判断当前客户端是否是游客
     *
     * @return true 如果是游客
     */
    public boolean isGuest() {
        return this.guestSessionId != null;
    }

    /**
     * 获取当前会话的键
     *
     * @return session key
     */
    public String getSessionKey() {
        if (isGuest()) {
            return "guest:" + this.guestSessionId;
        } else {
            return "user:" + currentUser.getId();
        }
    }

    private Map<String, Object> createUserStatusMap() {
        if(isGuest()){
            return null;
        }
        return MapUtil.objectToMap(this.currentUser);
    }

    /**
     * 获取当前用户状态信息
     *
     * @return 用户状态 Map
     */
    public Map<String, Object> getCurrentUserStatus() {
        return createUserStatusMap();
    }

    /**
     * 关闭连接，释放资源
     */
    private void closeConnection() {
        running = false;
        SessionManager.removeSessionByHandler(this);

        try {
            try (socket) {
                if (in != null) in.close();
                if (out != null) out.close();
            }
        } catch (IOException e) {
            logger.error("关闭连接失败 , {}",e.getMessage());
        }

        logger.info("连接已关闭: {}",socket.getRemoteSocketAddress());
    }
}
